using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.Xna.Framework.Storage;

namespace One_Crappy_RPG
{
    public class TileMap
    {
        public static int TileSize = 100;
        public Dictionary<int, List<Monster>> Encounters = new Dictionary<int, List<Monster>>();

        //Layer 0 = base layer, should all be grass/dirt etc
        //Layer 1 = Collision layer, use -1 for walkable space and place mountains,
        //          water, and other untraversable terrain here
        //Layer 2 = Level layer, used to pull monsters from the encounter dictionary
        public List<TileLayer> Layers;

        public TileMap(List<TileLayer> layers)
        {
            Layers = layers;
        }

        public TileMap()
        {
            Layers = new List<TileLayer>();
        }

        public void AddLayer(TileLayer layer)
        {
            Layers.Add(layer);
        }

        public void RemoveLayer(int index)
        {
            Layers.RemoveAt(index);
        }

        public void RemoveLayer(TileLayer layer)
        {
            Layers.Remove(layer);
        }

        public void Draw(SpriteBatch batch)
        {
            Layers[0].Draw(batch);
            Layers[1].Draw(batch);
        }

        public static TileMap FromFile(ContentManager content, string name)
        {
            TileMap map = new TileMap() ;
            TileLayer tempLayer = null;

            bool readingTextures = false;
            bool readingLayer = false;
            List<string> textureNames = new List<string>();
            List<List<int>> layerCells = new List<List<int>>();

            using (StreamReader reader = new StreamReader("Maps/" + name))
            {
                while (!reader.EndOfStream)
                {
                    string line = reader.ReadLine().Trim();

                    if (string.IsNullOrEmpty(line))
                        continue;

                    if (line.Contains("[Textures]"))
                    {
                        readingTextures = true;
                        readingLayer = false;                        
                    }
                    else if (line.Contains("[Layer]") || reader.EndOfStream)
                    {
                        readingLayer = true;
                        readingTextures = false;

                        //Piece together the old layer...                        
                        int height = layerCells.Count;

                        //...if it exists
                        if (height > 0)
                        {
                            int width = layerCells[0].Count;

                            tempLayer = new TileLayer(height, width);

                            for (int y = 0; y < height; y++)
                                for (int x = 0; x < width; x++)
                                    tempLayer.SetCellIndex(x, y, layerCells[y][x]);


                            tempLayer.LoadTextures(content, textureNames.ToArray());

                            map.Layers.Add(tempLayer);
                        }

                        layerCells.Clear();
                        textureNames.Clear();
                    }
                    else if (readingTextures)
                    {
                        textureNames.Add(line);
                    }
                    else if (readingLayer)
                    {
                        List<int> row = new List<int>();

                        string[] cells = line.Split(' ');

                        foreach (string c in cells)
                        {
                            if (!string.IsNullOrEmpty(c))
                                row.Add(int.Parse(c));
                        }

                        layerCells.Add(row);
                    }
                }

            }

            return map;
        }


        /// <summary>
        /// Gets a random 1-3 monsters on the player's tile
        /// </summary>
        /// <returns>List of Monsters</returns>
        public List<Monster> GetEncounter(Hero player)
        {
            //Pull the level from the cell
            int encounterLevel = Layers[2].GetCellIndex(player as Creature);

            Random rng = new Random();

            //Determine the max number of monsters in the battle
            int numMonsters = rng.Next(3) + 1;

            List<Monster> Battle = new List<Monster>(numMonsters);
            float chanceToSpawn = 1.0f / (float)Encounters[encounterLevel].Count;

            //Fill up the battle list
            do
            {
                //Loop through the available monsters
                foreach (Monster monster in Encounters[encounterLevel])
                {
                    //Give each an equal chance to appear in the fight
                    if ((float)rng.NextDouble() <= chanceToSpawn)
                    {
                        Battle.Add(new Monster(monster.Name, encounterLevel));
                        break;
                    }
                }
            } while (Battle.Count < Battle.Capacity);

            return Battle;
        }
    }
}
